import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:sentry/sentry.dart';
import 'dart:async';

import 'package:my_frist_flutter_app/cookbook/forms/create_and_style_a_text_field.dart';
import 'package:my_frist_flutter_app/cookbook/forms/building_a_form_with_validation.dart';
import 'package:my_frist_flutter_app/cookbook/forms/focus_on_a_text_field.dart';
import 'package:my_frist_flutter_app/cookbook/forms/handling_changes_to_a_text_field.dart';
import 'package:my_frist_flutter_app/cookbook/forms/retrieve_the_value_of_a_text_field.dart';
import 'package:my_frist_flutter_app/demo.dart';
import 'package:my_frist_flutter_app/demo1.dart';
import 'package:my_frist_flutter_app/demo2.dart';
import 'package:my_frist_flutter_app/cookbook/gestures/adding_material_touch_ripples.dart';
import 'package:my_frist_flutter_app/cookbook/gestures/handling_taps.dart';
import 'package:my_frist_flutter_app/cookbook/gestures/implement_swipe2dismiss.dart';
import 'package:my_frist_flutter_app/cookbook/image/learn_Image.dart';
import 'package:my_frist_flutter_app/cookbook/lists/basic_list.dart';
import 'package:my_frist_flutter_app/cookbook/lists/horizontal_list.dart';
import 'package:my_frist_flutter_app/cookbook/lists/grid_list.dart';
import 'package:my_frist_flutter_app/cookbook/lists/list_with_different_types_items.dart';
import 'package:my_frist_flutter_app/cookbook/lists/floating_app_bar_above_list.dart';
import 'package:my_frist_flutter_app/cookbook/lists/long_list.dart';
import 'package:my_frist_flutter_app/cookbook/maintenance/error_repoting.dart';
import 'package:my_frist_flutter_app/cookbook/navigation/hero_animations.dart';
import 'package:my_frist_flutter_app/cookbook/navigation/navigation_basics.dart';
import 'package:my_frist_flutter_app/cookbook/navigation/named_routes.dart';
import 'package:my_frist_flutter_app/cookbook/navigation/navigate_with_arguments.dart';
import 'package:my_frist_flutter_app/cookbook/navigation/returning_data.dart';
import 'package:my_frist_flutter_app/cookbook/navigation/passing_data.dart';
import 'package:my_frist_flutter_app/cookbook/networking/fetch_data.dart';
import 'package:my_frist_flutter_app/cookbook/networking/authenticated_requests.dart';
import 'package:my_frist_flutter_app/cookbook/networking/background_parsing.dart';
import 'package:my_frist_flutter_app/cookbook/networking/web_sockets.dart';
import 'package:my_frist_flutter_app/cookbook/persistence/sqlite.dart';
import 'package:my_frist_flutter_app/cookbook/persistence/reading_writing_files.dart';
import 'package:my_frist_flutter_app/cookbook/plugins/play_video.dart';
import 'package:my_frist_flutter_app/cookbook/plugins/picture_using_camera.dart';

final SentryClient _sentry = SentryClient(
    dsn: "https://398459bfecef404aba0799fae3df93f6@sentry.io/1465127");

/// Whether the VM is running in debug mode.
///
/// This is useful to decide whether a report should be sent to sentry. Usually
/// reports from dev mode are not very useful, as these happen on developers'
/// workspaces rather than on users' devices in production.
bool get isInDebugMode {
  bool inDebugMode = false;
  // assert(inDebugMode = true);
  return inDebugMode;
}

/// Reports [error] along with its [stackTrace] to Sentry.io.
Future<Null> _reportError(dynamic error, dynamic stackTrace) async {
  print('Caught error: $error');

  // Errors thrown in development mode are unlikely to be interesting. You can
  // check if you are running in dev mode using an assertion and omit sending
  // the report.
  if (isInDebugMode) {
    print(stackTrace);
    print('In dev mode. Not sending report to Sentry.io.');
    return;
  }

  print('Reporting to Sentry.io...');

  final SentryResponse response = await _sentry.captureException(
    exception: error,
    stackTrace: stackTrace,
  );

  if (response.isSuccessful) {
    print('Success! Event ID: ${response.eventId}');
  } else {
    print('Failed to report to Sentry.io: ${response.error}');
  }
}

Future<Null> main() async {
  // This captures errors reported by the Flutter framework.
  FlutterError.onError = (FlutterErrorDetails details) async {
    if (isInDebugMode) {
      // In development mode simply print to console.
      FlutterError.dumpErrorToConsole(details);
    } else {
      // In production mode report to the application zone to report to
      // Sentry.
      Zone.current.handleUncaughtError(details.exception, details.stack);
    }
  };

  // This creates a [Zone] that contains the Flutter application and stablishes
  // an error handler that captures errors and reports them.
  //
  // Using a zone makes sure that as many errors as possible are captured,
  // including those thrown from [Timer]s, microtasks, I/O, and those forwarded
  // from the `FlutterError` handler.
  //
  // More about zones:
  //
  // - https://api.dartlang.org/stable/1.24.2/dart-async/Zone-class.html
  // - https://www.dartlang.org/articles/libraries/zones
  runZoned<Future<Null>>(() async {
    runApp(Index());
  }, onError: (error, stackTrace) async {
    await _reportError(error, stackTrace);
  });
}

class Index extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dart Demo'),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.shopping_cart),
              tooltip: 'Open shopping cart',
              onPressed: () {
                // Implement navigation to shopping cart page here...
                print('Shopping cart opened.');
              },
            ),
          ],
        ),
        body: ListViewPage(),
      ),
    );
  }
}

class ListViewPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        getListItem(context, 'demo:demo', () => Demo()),
        getListItem(context, 'demo:demo1', () => Demo1()),
        getListItem(context, 'demo:demo2', () => Demo2()),
        getListItem(
            context, 'form:building_a_form_with_validation', () => FormDemo()),
        getListItem(context, 'form:create_and_style_a_text_field',
            () => TextFieldDemo()),
        getListItem(context, 'form:focus_on_a_text_field',
            () => FocusOnTextFeildDemo()),
        getListItem(context, 'form:handling_changes_to_a_text_field',
            () => HandlingChangesToTextFieldDemo()),
        getListItem(context, 'form:retrieve_the_value_of_a_text_field',
            () => RetrieveValueOfTextFieldDemo()),
        getListItem(context, 'gestures:adding_material_touch_ripples',
            () => AddingMaterialTouchRipplesDemo()),
        getListItem(
            context, 'gestures:handling_taps', () => HandlingTapsDemo()),
        getListItem(context, 'gestures:implement_swipe2dismiss',
            () => ImplementSwipe2DismissDemo()),
        getListItem(context, 'images:learn_Image', () => WebImageDemo()),
        getListItem(context, 'lists:basic_list', () => BasicListDemo()),
        getListItem(
            context, 'lists:horizontal_list', () => HorizontalListDemo()),
        getListItem(context, 'lists:grid_list', () => GridListDmeo()),
        getListItem(context, 'lists:list_with_different_types_items',
            () => ListWithDifferentItemsDemo()),
        getListItem(context, 'lists:floating_app_bar_above_list',
            () => FloatingAppBarAboveListDemo()),
        getListItem(context, 'lists:long_list', () => LongListDemo()),
        getListItem(
            context, 'lists:error_repoting', () => ErrorReportingDemo()),
        getListItem(context, 'navigation:hero_animations', () => HeroDemo()),
        getListItem(
            context, 'navigation:navigation_basics', () => NavigationDemo()),
        getListItem(context, 'navigation:named_routes', () => NamedRouteDemo()),
        getListItem(context, 'navigation:navigate_with_arguments',
            () => NavigateWithArgumentsDemo()),
        getListItem(
            context, 'navigation:returning_data', () => ReturningDataDemo()),
        getListItem(
            context, 'navigation:passing_data', () => PassingDateDemo()),
        getListItem(context, 'networking:fetch_data', () => FetchDataDemo()),
        getListItem(context, 'networking:authenticated_requests',
            () => AuthenticatedRequestsDemo()),
        getListItem(context, 'networking:background_parsing',
            () => BackgroundParsingDemo()),
        getListItem(context, 'networking:web_sockets', () => WebSocketsDemo()),
        getListItem(context, 'persistence:sqlite', () => SqliteDemo()),
        getListItem(
            context, 'persistence:reading_writing_files', () => FileDemo()),
        getListItem(context, 'plugin:play_video', () => VideoPlayerApp()),
        getListItem(context, 'plugin:picture_using_camera', () => takePictureDemo()),
      ],
    );
  }

  Widget getListItem(
      BuildContext context, String title, dynamic Function() pageGenerator) {
    return ListTile(
      title: Text(title),
      onTap: () async {
        Widget page;
        print(pageGenerator);
        if (pageGenerator is Widget Function()) {
          print('pageGenerator is Widget');
          page = pageGenerator();
        } else if (pageGenerator is Future<Widget> Function()) {
          print('pageGenerator is Future<Widget>');
          page = await pageGenerator();
        } else {
          print('pageGenerator is not expected');
          return;
        }
        print(page);
        Navigator.of(context)
            .push(MaterialPageRoute(builder: (BuildContext context) {
          return page;
        }));
      },
    );
  }
}
